home *** CD-ROM | disk | FTP | other *** search
- /**\
- |**| CloseViewMP.c
- \**/
-
- #include "CloseViewMP.h"
-
- // typdef's, struct's, define's, enum's, etc.
-
- #define kMPStackSize 0 // use default stack size
- #define kMPTaskOptions 0 // use no options
-
- typedef struct MyTaskStruct {
- MPTaskID fTaskID;
- MPTaskWeight fWeight;
- }MyTaskRec,*MyTaskPtr,**MyTaskHdl;
-
- typedef struct MyGDInfo {
- GDHandle fGDHdl;
- PixMapHandle fPixMapHdl;
- Ptr fBaseAddr;
- Rect fRect;
- }MyGDInfoRec,*MyGDInfoPtr,**MyGDInfoHdl;
-
- // external globals
-
- UInt32 gMag = 1;
-
- // local (static) globals & const
-
- static Boolean gPaused = false;
- static Boolean gLoop = true;
-
- #if !SMP_TEST
- static MPQueueID gNotificationQueueID;
- static MyTaskRec gMyTaskRec;
- static MPSemaphoreID gSemaphoreID;
- #endif !SMP_TEST
-
- static MenuHandle gContextualMenuHdl = nil;
-
- static const SInt16 gMags[] = {25,50,100,200,400,800,1600,3200,6400,9999};
-
- static Point gMidPoint = {-1,-1};
-
- static Rect gSrcRect = {-1,-1,-1,-1};
- static Rect gDstRect = {-1,-1,-1,-1};
-
- static PixMapHandle gSrcPixMapHdl = nil;
- static PixMapHandle gDstPixMapHdl = nil;
-
- static Ptr gSrcBaseAddr = nil;
- static Ptr gDstBaseAddr = nil;
-
- static MyGDInfoRec gMyGDInfoRec[8]; // nobody's got more than 8 monitors
-
- // local function prototypes
- static OSStatus MyTask(void* pMyTaskPtr);
- static void Blit_All(void);
- static void Blit_One(const Rect* pSrcRect,const Rect* pDstRect);
-
- static Boolean Point2_In_Rect(const short pH,const short pV,const Rect* pRect);
- static Boolean Intersect_Rects(const Rect* pRect1,Rect* pRect2);
- static void Set_Rect(
- Rect *r,
- const short pLeft,
- const short pTop,
- const short pRight,
- const short pBottom);
-
- static void Offset_Rect(Rect *r,const short pDh,const short pDv);
-
- static SInt16 random();
-
- #define ABS(x) ((x) < 0 ? -(x) : (x))
-
- // local functions
-
- /**\
- |**| Initialize everything for CloseViewMP, make sure we can run
- \**/
-
- OSStatus CVMP_Init(UInt32 pMag)
- {
- OSStatus error;
-
- if (!MPLibraryIsLoaded())
- return kMPInsufficientResourcesErr;
-
- CVMP_Reset();
-
- // Initialize remaining globals
- gNotificationQueueID = NULL;
- gMag = pMag;
-
- // create the notification queue
- error = MPCreateQueue(&gNotificationQueueID);
- if (error != noErr)
- return error;
-
- // create the task
- {
- gMyTaskRec.fWeight = 100;
-
- # if !SMP_TEST
- error = MPCreateTask(MyTask, &gMyTaskRec, // task entry point & parameter
- kMPStackSize, gNotificationQueueID, // stack size & notification queue ID
- &gMyTaskRec, NULL, kMPTaskOptions, // Notify params 1 & 2 and task options
- &gMyTaskRec.fTaskID); // task id
- if (error != noErr)
- {
- DebugStr("\p|CVMP_Init-F-MPCreateTask error.;g");
- return error;
- }
-
- error = MPSetTaskWeight(gMyTaskRec.fTaskID,gMyTaskRec.fWeight);
- if (error != noErr)
- {
- DebugStr("\p|CVMP_Init-F-MPSetTaskWeight error.;g");
- return error;
- }
-
- // create the work semaphore
- error = MPCreateSemaphore(256, 0, &gSemaphoreID);
- if (error != noErr)
- {
- DebugStr("\p|CVMP_Init-F-MPCreateSemaphore error.;g");
- return error;
- }
- # endif !SMP_TEST
- }
-
- // gContextualMenuHdl = GetMenu(mWeightMenu);
- // InsertMenu(gContextualMenuHdl, -1);
-
- return error;
- } // CVMP_Init
-
- /**\
- |**| Cleanup everything
- \**/
-
- void CVMP_Term(void)
- {
- OSStatus error;
-
- gPaused = gLoop = false;
-
- if (gMyTaskRec.fTaskID != NULL)
- {
- // terminate this task
- error = MPTerminateTask(gMyTaskRec.fTaskID, kMPTaskAbortedErr);
- // if (error != noErr)
- // DebugStr("\p|CVMP_Term-F-MPTerminateTask error.;");
-
- // Now wait for notification that this task has terminated
- while ((error = MPWaitOnQueue(gNotificationQueueID,
- NULL, NULL, NULL, kDurationImmediate)) == noErr)
- {
- if (gMyTaskRec.fTaskID != NULL)
- gMyTaskRec.fTaskID = NULL;
- }
- }
-
- // delete the notification queue
- if (gNotificationQueueID != NULL)
- {
- MPDeleteQueue(gNotificationQueueID);
- gNotificationQueueID = NULL;
- }
- }
-
- /**\
- |**| Handle a null event
- \**/
-
- void CVMP_DoNull(void)
- {
- CVMP_Reset();
- # if SMP_TEST
- gLoop = false;
- MyTask((void*) &gMyTaskRec);
- # else
- // MPYield();
- # endif SMP_TEST
- }
-
- /**\
- |**| Handle a mouse down event
- \**/
-
- void CVMP_DoClick(const EventRecord *pEventPtr)
- {
- Point where = pEventPtr->where;
-
- GlobalToLocal(&where);
-
- SysBeep(15);
- }
-
- /**\
- |**| set mag
- \**/
-
- UInt16 CVMP_SetMag(UInt16 pMag)
- {
- UInt16 result = gMag;
- gMag = pMag;
-
- CVMP_Reset();
-
- return result;
- }
-
- /**\
- |**| get mag
- \**/
-
- UInt16 CVMP_GetMag(void)
- {
- return gMag;
- }
-
- /**\
- |**| set weight
- \**/
-
- void CVMP_SetWeight(UInt16 pIndex)
- {
- if ((pIndex > 0) && (pIndex <= 10))
- {
- OSErr error;
-
- gMyTaskRec.fWeight = gMags[pIndex];
-
- error = MPSetTaskWeight(gMyTaskRec.fTaskID, gMyTaskRec.fWeight);
- if (error != noErr)
- DebugStr("\p|CVMP_SetMag-F-MPSetTaskWeight error.;g");
- }
- else
- SysBeep(15);
- }
-
- void CVMP_SetMidPoint(Point pPoint)
- {
- if (gWindowPtr && !EqualPt(pPoint,gMidPoint))
- {
- gMidPoint = pPoint;
-
- CVMP_Reset();
- }
- }
-
- /**\
- |**| Reset the mag info
- \**/
-
- void CVMP_Reset(void)
- {
- GDHandle nthDevice;
- UInt32 index = 0;
-
- gPaused = true; // pause blitter
- gDstRect = gWindowRect;
-
- for (nthDevice = DMGetFirstScreenDevice(true);nthDevice;
- nthDevice = DMGetNextScreenDevice(nthDevice,true))
- {
- gMyGDInfoRec[index].fGDHdl = nthDevice;
- gMyGDInfoRec[index].fPixMapHdl = (*nthDevice)->gdPMap;
- gMyGDInfoRec[index].fBaseAddr = GetPixBaseAddr(gMyGDInfoRec[index].fPixMapHdl);
- gMyGDInfoRec[index].fRect = (*nthDevice)->gdRect;
- index++;
- }
-
- // zero the rest of the records
- for (;index < 8;index++)
- {
- gMyGDInfoRec[index].fGDHdl = nil;
- gMyGDInfoRec[index].fPixMapHdl = nil;
- gMyGDInfoRec[index].fBaseAddr = nil;
- }
- gLoop = true;
- if (gWindowPtr)
- { // if the window is unobscured
- static RgnHandle visRgn = nil;
- static RgnHandle contRgn = nil;
-
- if (nil == visRgn)
- visRgn = NewRgn();
-
- if (nil == contRgn)
- contRgn = NewRgn();
-
- if (visRgn && contRgn)
- {
- #if TARGET_API_MAC_CARBON
- Rect visRect,contRect;
-
- GetWindowRegion(gWindowPtr,kWindowContentRgn,contRgn);
- GetPortVisibleRegion(GetWindowPort(gWindowPtr),visRgn);
-
- GetRegionBounds(contRgn,&contRect);
- GetRegionBounds(visRgn,&visRect);
-
- OffsetRgn(visRgn,contRect.left - visRect.left,contRect.top - visRect.top);
- #else
- CopyRgn(((WindowPeek) gWindowPtr)->contRgn,contRgn);
- CopyRgn(gWindowPtr->visRgn,visRgn);
-
- OffsetRgn(visRgn,
- (*contRgn)->rgnBBox.left - (*visRgn)->rgnBBox.left,
- (*contRgn)->rgnBBox.top - (*visRgn)->rgnBBox.top);
- #endif TARGET_API_MAC_CARBON
-
- if (EqualRgn(visRgn,contRgn))
- gPaused = false; // unpause blitter
- }
- CVMP_Update();
- }
- }
-
- /**\
- |**| This causes the blit task to break out of its slumber.
- \**/
-
- void CVMP_Update(void)
- {
- #if !SMP_TEST
- MPSignalSemaphore(gSemaphoreID);
- #endif
- }
-
- /**\
- |**| set & return the paused state
- \**/
-
- extern Boolean CVMP_Pause(Boolean pPaused)
- {
- Boolean result = gPaused;
- gPaused = pPaused;
-
- return result;
- }
-
- /**\
- |**| This is the MP task entrypoint
- \**/
-
- static OSStatus MyTask(void* pMyTaskPtr)
- {
- Point oldMousePoint = {-1,-1},mousePoint;
- (pMyTaskPtr); // #pragma unused (pMyTaskPtr)
-
- // Blit the data periodically but at a low refresh rate. the main task
- // will signal if it has demand blitting to do.
- do {
- Blit_All();
-
- do {
- SInt32 index;
-
- for (index = 0;index < 12;index++)
- {
- #if !SMP_TEST
- if (noErr == MPWaitOnSemaphore(gSemaphoreID, 33 * kDurationMillisecond))
- break;
- #endif !SMP_TEST
-
- #if TARGET_API_MAC_CARBON
- GetGlobalMouse(&mousePoint);
- #else
- mousePoint = LMGetMouseLocation();
- #endif TARGET_API_MAC_CARBON
- if (oldMousePoint.v != mousePoint.v || oldMousePoint.h != mousePoint.h)
- {
- oldMousePoint = mousePoint;
- break;
- }
- }
-
- } while (gPaused && gLoop);
- } while (gLoop);
-
- return noErr;
- }
-
- /**\
- |**| Blit All
- \**/
-
- static void Blit_All(void)
- {
- SInt32 srcIndex,dstIndex;
-
- #if TARGET_API_MAC_CARBON
- GetGlobalMouse(&gMidPoint);
- #else
- gMidPoint = LMGetMouseLocation();
- #endif TARGET_API_MAC_CARBON
-
- for (dstIndex = 0;dstIndex < 8;dstIndex++)
- {
- if (gMyGDInfoRec[dstIndex].fGDHdl)
- {
- Rect dstRect = gDstRect;
-
- if (Intersect_Rects(&gMyGDInfoRec[dstIndex].fRect,&dstRect))
- {
- gDstPixMapHdl = gMyGDInfoRec[dstIndex].fPixMapHdl;
- gDstBaseAddr = gMyGDInfoRec[dstIndex].fBaseAddr;
-
- Set_Rect(&gSrcRect,0,0,
- ((dstRect.right - dstRect.left) / gMag) + 1,
- ((dstRect.bottom - dstRect.top) / gMag) + 1);
-
- Offset_Rect(&gSrcRect,
- gMidPoint.h - ((gSrcRect.left + gSrcRect.right) >> 1),
- gMidPoint.v - ((gSrcRect.top + gSrcRect.bottom) >> 1));
-
- for (srcIndex = 0;srcIndex < 8;srcIndex++)
- {
- if (gMyGDInfoRec[srcIndex].fGDHdl)
- {
- Rect srcRect = gSrcRect;
-
- // if (Intersect_Rects(&gMyGDInfoRec[srcIndex].fRect,&srcRect))
- if (Point2_In_Rect(gMidPoint.h,gMidPoint.v,&gMyGDInfoRec[srcIndex].fRect))
- {
- gSrcPixMapHdl = gMyGDInfoRec[srcIndex].fPixMapHdl;
- gSrcBaseAddr = gMyGDInfoRec[srcIndex].fBaseAddr;
-
- Blit_One(&gSrcRect,&dstRect);
- }
- }
- }
- }
- }
- }
- }
-
- static void Blit_One(const Rect* pSrcRect,const Rect* pDstRect)
- {
- if (gSrcPixMapHdl && gDstPixMapHdl)
- {
- Rect srcBounds = (*gSrcPixMapHdl)->bounds;
- UInt32 srcBytesPerPixel = (*gSrcPixMapHdl)->pixelSize / 8;
- UInt32 srcSkip = (*gSrcPixMapHdl)->rowBytes & 0x3FFF;
- Ptr srcBase = gSrcBaseAddr +
- (srcSkip * (pSrcRect->top - srcBounds.top)) +
- ((pSrcRect->left - srcBounds.left) * srcBytesPerPixel);
-
- Rect dstBounds = (*gDstPixMapHdl)->bounds;
- UInt32 dstBytesPerPixel = (*gDstPixMapHdl)->pixelSize / 8;
- UInt32 dstSkip = (*gDstPixMapHdl)->rowBytes & 0x3FFF;
- Ptr dstBase = gDstBaseAddr +
- (dstSkip * (pDstRect->top - dstBounds.top)) +
- ((pDstRect->left - dstBounds.left) * dstBytesPerPixel);
-
- SInt32 dstRow,dstCol,srcRow,srcCol,magRow,magCol;
-
- magRow = 0;
- srcRow = pSrcRect->top;
- for (dstRow = pDstRect->top;dstRow < pDstRect->bottom;dstRow++)
- {
- Ptr srcPtr = srcBase,dstPtr = dstBase;
- UInt32 color32 = -1;
- UInt16 color16 = -1;
- UInt8 color8 = -1;
-
- magCol = 0;
- srcCol = pSrcRect->left;
- for (dstCol = pDstRect->left;dstCol < pDstRect->right;dstCol++)
- {
- if (!magCol)
- {
- if ((srcRow >= srcBounds.top) &&
- (srcRow < srcBounds.bottom) &&
- (srcCol >= srcBounds.left) &&
- (srcCol < srcBounds.right))
- {
- color32 = *(UInt32*) srcPtr;
- color16 = color32 >> 16;
- color8 = color16 >> 8;
- }
- else
- color32 = color16 = color8 = 0;
-
- srcPtr += srcBytesPerPixel;
- srcCol++;
- }
-
- if ((dstRow >= dstBounds.top) &&
- (dstRow < dstBounds.bottom) &&
- (dstCol >= dstBounds.left) &&
- (dstCol < dstBounds.right))
- {
- switch (dstBytesPerPixel)
- {
- case 1: // 256 colors
- *dstPtr = color8;
- break;
- case 2: // thousand colors
- *(UInt16*) dstPtr = color16;
- break;
- case 4: // million colors
- *(UInt32*) dstPtr = color32;
- break;
- }
- }
- dstPtr += dstBytesPerPixel;
-
- magCol++;
- magCol %= gMag;
- }
- magRow++;
- magRow %= gMag;
- if (!magRow)
- {
- srcBase += srcSkip;
- srcRow++;
- }
- dstBase += dstSkip;
- }
- }
- }
-
- /**\
- |**| Test to see if a point is in a rect
- \**/
-
- static Boolean Point2_In_Rect(const short pH,const short pV,const Rect* pRect)
- {
- if (pV < pRect->top)
- return false;
- if (pV >= pRect->bottom)
- return false;
- if (pH < pRect->left)
- return false;
- if (pH >= pRect->right)
- return false;
- return true;
- }
-
- static void Set_Rect(Rect *r,
- const short pLeft,
- const short pTop,
- const short pRight,
- const short pBottom)
- {
- r->top = pTop;
- r->right = pRight;
- r->bottom = pBottom;
- r->left = pLeft;
- }
-
- /**\
- |**| aBool = SectRect(src1,src2,dstRect);
- \**/
-
- static Boolean Intersect_Rects(const Rect* pRect1,Rect* pRect2)
- {
- if (pRect2->top < pRect1->top)
- pRect2->top = pRect1->top;
-
- if (pRect2->bottom > pRect1->bottom)
- pRect2->bottom = pRect1->bottom;
-
- if (pRect2->left < pRect1->left)
- pRect2->left = pRect1->left;
-
- if (pRect2->right > pRect1->right)
- pRect2->right = pRect1->right;
-
- if ((pRect2->top < pRect2->bottom) &&
- (pRect2->left < pRect2->right))
- return true;
- else
- return false;
- }
-
- /**\
- |**| move a rectangle
- \**/
-
- static void Offset_Rect(Rect *r,const short pDh,const short pDv)
- {
- r->top += pDv;
- r->left += pDh;
- r->bottom += pDv;
- r->right += pDh;
- }
-
- /**\
- |**| generate a random number +/- 32768
- \**/
-
- static SInt16 random()
- {
- static SInt32 state = 314159;
-
- state = ((state * 1103515245) + 12345 ) & 0x7fffffff;
-
- return ((state >> 6) & 0xffff);
- }
-
-